home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Resource Library: Multimedia
/
Resource Library: Multimedia.iso
/
hypercrd
/
xcmds
/
tffdsply.hqx
/
tifflzw.c
< prev
next >
Wrap
Text File
|
1993-01-04
|
3KB
|
124 lines
/*
* This software is copyright 1992 by Robert Morris.
* You may freely redistribute this software as shareware
* if you do so in the same form as you got it. If you find
* this software useful, please send $12 to:
* Robert Morris
* P.O. Box 1044
* Harvard Square Station
* Cambridge, MA 02238
* ecognome@aol.com
* If you incorporate any of this software in any kind of
* commercial product, please send $2 per copy distributed
* to the above address.
*/
#include "tiffinfo.h"
/*
* Lempel-Ziv decompression for TIFF. inlen is the actual number of input
* characters, and outlen is the number of expected output characters.
* out[] has size outlen, so it is an error if there are more than outlen
* characters produced. UnLZW() returns 0 if everything was fine, and
* < 0 if there was some problem.
*/
/*
* If a code is < 256, it is that character. 256 is the Clear code, and
* 257 is the end-of-information code. Otherwise it refers to a string
* previously produced as output, followed by a single character.
*/
struct stringtable{
long index;
long len;
};
#define ClearCode 256
#define EndOfInformation 257
void
ClearTable(struct stringtable *table)
{
int i;
for(i = 0; i < 256; i++){
table[i].index = 0;
table[i].len = 0;
}
}
int
UnLZW(char *in, long inlen, char *out, long outlen)
{
struct stringtable *table = 0;
int ncodes; /* # of codes in the table */
int codelen; /* current code length in bits */
unsigned short *ip; /* current point in input */
int bit; /* # of (high) bits consumed in *ip */
char *op; /* next element to write in out[] */
unsigned short code;
int i;
table = (struct stringtable *) NewPtr(sizeof(struct stringtable) * 4096);
if(table == 0)
return(MemError());
ClearTable(table);
ncodes = 258; /* one for each 8-bit character, plus two special codes */
codelen = 9;
op = out;
ip = (unsigned short *) in;
bit = 0;
while(1){
if((char *)ip >= in + inlen){
/* ran out of information before we saw EndOfInformation! */
goto bad;
}
if(bit >= 16){
ip++;
bit = 0;
}
code = (*ip << bit) >> (16 - codelen);
bit += codelen;
if(bit > 16){
/* need to read some more */
ip++;
bit -= 16;
code |= (*ip >> (16 - bit));
}
if(code == ClearCode){
ncodes = 258;
codelen = 9;
} else if(code == EndOfInformation){
break;
} else if(code < ncodes){
if(op + table[code].len > out + outlen)
goto bad;
table[ncodes].index = op - out;
if(code < 256){
*op++ = code;
table[ncodes].len = 2;
} else {
for(i = 0; i < table[code].len; i++)
*op++ = out[table[code].index + i];
table[ncodes].len = table[code].len + 1;
}
ncodes++;
if(ncodes == (1 << codelen))
codelen++;
} else {
/* code out of range */
goto bad;
}
}
DisposPtr(table);
return(0);
bad:
if(table)
DisposPtr(table);
return(-1);
}